﻿
using Infrastructure.Extensions;
using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.Reflection;
using ZR.Infrastructure.Model;
using SqlSugar;
using System.Linq;

namespace Infrastructure
{
    public static class EntityExtension
    {
        private static readonly EntityAutoFillFieldModel AutoFillField = new EntityAutoFillFieldModel
        {
            PKType= PKTypeEnum.IdentityId,
            CreateTimeField = "Create_time",
            CreaterField= "Create_by",
            CreaterIdField="",
            UpdaterField= "Update_by",
            UpdaterIdField="",
            UpdateTimeField= "Update_time"
        };

        public static readonly EntityAutoFillFieldModel AutoFillField2 = new EntityAutoFillFieldModel
        {
            PKType = PKTypeEnum.SnowId,
            CreateTimeField = "CreateTime",
            CreaterField = "Creater",
            CreaterIdField = "CreaterId",
            UpdaterField = "Modifier",
            UpdaterIdField = "ModifierId",
            UpdateTimeField = "ModifyTime"
        };

        public static TSource ToCreate<TSource>(this TSource source, HttpContext? context = null,
            EntityAutoFillFieldModel autoFillField=null)
        {
            var type = source?.GetType();
            if (type == null || context == null) return source;
            BindingFlags flag = BindingFlags.Public | BindingFlags.IgnoreCase | BindingFlags.Instance;

            if(autoFillField == null)
            {
                autoFillField = AutoFillField;
            }
            if (!string.IsNullOrWhiteSpace(autoFillField.CreateTimeField))
            {
                type.GetProperty(autoFillField.CreateTimeField, flag)?.SetValue(source, DateTime.Now, null);
            }
            if (!string.IsNullOrWhiteSpace(autoFillField.CreaterField))
            {
                type.GetProperty(autoFillField.CreaterField, flag)?.SetValue(source, context.GetName(), null);
            }
            if (!string.IsNullOrWhiteSpace(autoFillField.CreaterIdField))
            {
                type.GetProperty(autoFillField.CreaterIdField, flag)?.SetValue(source, context.GetUId(), null);
            }
            if (!string.IsNullOrWhiteSpace(autoFillField.UpdateTimeField))
            {
                type.GetProperty(autoFillField.UpdateTimeField, flag)?.SetValue(source, DateTime.Now, null);
            }
            if (!string.IsNullOrWhiteSpace(autoFillField.UpdaterField))
            {
                type.GetProperty(autoFillField.UpdaterField, flag)?.SetValue(source, context.GetName(), null);
            }
            if (!string.IsNullOrWhiteSpace(autoFillField.UpdaterIdField))
            {
                type.GetProperty(autoFillField.UpdaterIdField, flag)?.SetValue(source, context.GetUId(), null);
            }
            switch(autoFillField.PKType)
            {
                case PKTypeEnum.SnowId:
                    {
                        var pkField = type.GetProperties(BindingFlags.Public | BindingFlags.Instance)
                            .FirstOrDefault(f =>
                            {
                                var attr = f.GetCustomAttribute<SugarColumn>();
                                return f.PropertyType == typeof(long) && attr?.IsPrimaryKey==true;
                            });
                        if (pkField != null)
                        {
                            type.GetProperty(pkField.Name, flag)?.SetValue(source, SnowFlakeSingle.Instance.NextId(), null);
                        }
                    }
                    break;
                case PKTypeEnum.Guid:
                    {
                        var pkField = type.GetFields(BindingFlags.Public | BindingFlags.Instance)
                            .FirstOrDefault(f =>
                            {
                                var attr = f.GetCustomAttribute<SugarColumn>();
                                return f.FieldType == typeof(Guid) && attr?.IsPrimaryKey==true;
                            });
                        if (pkField != null)
                        {
                            type.GetProperty(pkField.Name, flag)?.SetValue(source, Guid.NewGuid(), null);
                        }
                    }
                    break;
                default:
                    break;
            }
            
            return source;
        }

        public static TSource ToUpdate<TSource>(this TSource source, HttpContext? context = null,
            EntityAutoFillFieldModel autoFillField = null)
        {
            var types = source?.GetType();
            if (types == null || context == null) return source;
            BindingFlags flag = BindingFlags.Public | BindingFlags.IgnoreCase | BindingFlags.Instance;
            if (autoFillField == null)
            {
                autoFillField = AutoFillField;
            }
            if (!string.IsNullOrWhiteSpace(autoFillField.UpdateTimeField))
            {
                types.GetProperty(autoFillField.UpdateTimeField, flag)?.SetValue(source, DateTime.Now, null);
            }
            if (!string.IsNullOrWhiteSpace(autoFillField.UpdaterField))
            {
                types.GetProperty(autoFillField.UpdaterField, flag)?.SetValue(source, context.GetName(), null);
            }
            if (!string.IsNullOrWhiteSpace(autoFillField.UpdaterIdField))
            {
                types.GetProperty(autoFillField.UpdaterIdField, flag)?.SetValue(source, context.GetUId(), null);
            }

            return source;
        }

    }
}
